package utils

import java.io.File

import org.apache.commons.io.FileUtils
import play.api.libs.json.Json
import shapeless.{HList, LabelledGeneric, Lazy}

import scala.concurrent.{Await, Future}
import scala.concurrent.duration.Duration
import implicits.Implicits._

import scala.collection.immutable.SeqMap
import scala.collection.mutable

/**
 * Created by yz on 2017/6/28.
 */
object Utils {

  val dbName = "cbgd_database"
  val windowsPath = s"E:\\${dbName}"
  val playPath = new File("../").getAbsolutePath
  val linuxPath = playPath + s"/${dbName}"

  val path = {
    if (new File(windowsPath).exists()) windowsPath else linuxPath
  }

  val paperPath = path + File.separator + "paper"
  val blastFile = new File(Utils.path, "ncbi-blast-2.6.0+/bin/blastn")
  val blast2HtmlFile = new File(Utils.path, "blast2html-82b8c9722996/blast2html.py")
  val samtoolsPath = if (new File(windowsPath).exists()) new File(Utils.path, "samtools-0.1.19/samtools").getAbsolutePath else "samtools"
  val HPbDataFile = new File(Utils.path, "H-PB-GapClose.fa")
  val HPbDataV2File = new File(Utils.path, "HG_genome_chr.fasta")
  val otherFaFile = new File(Utils.path, "Lsiceraria_v1.fa")
  val cdsDataFile = new File(Utils.path, "BottleGourd.gene.cds.final")
  val othercdsFile = new File(Utils.path, "Lsiceraria_v1.cds.fa")

  val scriptHtml =
    """
      |<script>
      |	$(function () {
      |			    $("footer:first").remove()
      |        $("#content").css("margin","0")
      |       $(".linkheader>a").each(function () {
      |				   var text=$(this).text()
      |				   $(this).replaceWith("<span style='color: #222222;'>"+text+"</span>")
      |			   })
      |
      |      $("tr").each(function () {
      |         var a=$(this).find("td>a:last")
      |					var text=a.text()
      |					a.replaceWith("<span style='color: #222222;'>"+text+"</span>")
      |				})
      |
      |       $("p.titleinfo>a").each(function () {
      |				   var text=$(this).text()
      |				   $(this).replaceWith("<span style='color: #606060;'>"+text+"</span>")
      |			   })
      |
      |       $(".param:eq(1)").parent().hide()
      |       $(".linkheader").hide()
      |
      |			})
      |</script>
    """.stripMargin

  def isWindows = {
    System.getProperty("os.name") match {
      case x if x.contains("Windows") => true
      case _ => false
    }
  }

  def isInteger(value: String): Boolean = {
    try {
      value.toInt
    } catch {
      case _: Exception =>
        return false
    }
    true
  }

  def execFuture[T](f: Future[T]): T = {
    Await.result(f, Duration.Inf)
  }

  def isDouble(value: String): Boolean = {
    try {
      value.toDouble
    } catch {
      case _: Exception =>
        return false
    }
    true
  }

  def isIntegerP(value: String, p: Int => Boolean): Boolean = {
    try {
      val int = value.toInt
      if (!p(int)) return false
    } catch {
      case _: Exception =>
        return false
    }
    true
  }

  def deleteDirectory(direcotry: File): Unit = {
    try {
      FileUtils.deleteDirectory(direcotry)
    } catch {
      case _ =>
    }
  }

  def deleteDirectory(tmpDir: String): Unit = {
    val direcotry = new File(tmpDir)
    deleteDirectory(direcotry)
  }

  def getTime(startTime: Long) = {
    val endTime = System.currentTimeMillis()
    val time = (endTime - startTime) / 1000.0
    time
  }

  def getJsonByTs[T, H <: HList](x: Seq[T])(implicit generic: LabelledGeneric.Aux[T, H],
                                            hc: Lazy[ObjectCodec[H]]) = {
    val array = getArrayByTs(x)
    Json.toJson(array)
  }

  def getArrayByTs[T, H <: HList](x: Seq[T])(implicit generic: LabelledGeneric.Aux[T, H],
                                             hc: Lazy[ObjectCodec[H]]) = {
    x.map { y =>
      y.myAsJson
    }
  }

  def getSeqMap(file: File) = {

    def loop(lines: List[String], acc: SeqMap[String, StringBuilder]): SeqMap[String, StringBuilder] = {
      lines match {
        case Nil => acc
        case x :: xs =>
          val newAcc = if (x.startsWith(">")) {
            acc + (x -> new StringBuilder())
          } else {
            val (key, stringBuilder) = acc.last
            val newStringBuilder = stringBuilder.append(x)
            acc.updated(key, newStringBuilder)
          }
          loop(xs, newAcc)
      }
    }

    loop(file.lines, SeqMap[String, mutable.StringBuilder]()).map { case (k, stringBuilder) =>
      (k -> stringBuilder.mkString)
    }
  }


}
